package edu.nf.api.controller.filter;

import com.google.gson.Gson;
import edu.nf.util.JwtUtil;
import edu.nf.vo.ResultVO;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Date 2023-06-20
 * @Author qiu
 * 用户认证
 */
@WebFilter("/user/*")
public class ZAuthFilter implements Filter {

    private static final String LOGIN = "login";
    private static final String OPTIONS = "options";
    private static final String TOKEN_HEADER = "Authorization";
    /**
     * token前缀，注意有个空格
     */
    private static final String TOKEN_PREFIX = "Bearer ";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("authFilter....");
    }

    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse,
                         FilterChain filterChain)
            throws IOException, ServletException {
        // 1.向下转型
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        // 2.获取请求方式 -- 对预检请求进行放行
        // 在跨域请求中，客户端会发起两次请求，
        // 第一次请求是预检请求（探路）是为了检查服务端是否开启跨域访问
        // 第二次请求是真正的请求，如果开启跨域，才发起第二次请求，否则结束请求
        String method = request.getMethod();
        if (OPTIONS.equalsIgnoreCase(method)) {
            return;
        }

        // 3.获取客户端发送过来 JWT 令牌字符串
        String token = request.getHeader(TOKEN_HEADER);
        if (token == null || "".equals(token)) {
            responseView(response, "请先登录");
            return;
        }

        // 4.验证token
        try {
            // 获取jwt
            token = token.replace(TOKEN_PREFIX,"").trim();

            JwtUtil.verify(token);

            String username = JwtUtil.getPayload(token, "username", String.class);

            if (username == null || "".equals(username)) {
                responseView(response, "解析token失败");
                return;
            }

            // 把当前登录的帐号设置在请求作用域中，传递具体的 Controller
            request.setAttribute("username",username);

            // 验证成功，放行
            filterChain.doFilter(request, response);
        } catch (Exception e) {
            responseView(response, "会话已失效");
        }

    }

    private void responseView(HttpServletResponse response, String message)
            throws IOException {
        ResultVO responseData = new ResultVO();
        responseData.setCode(401);
        responseData.setMsg(message);

        response.setContentType("application/json;charset=utf-8");
        String json = new Gson().toJson(responseData) ;

        PrintWriter out = response.getWriter();
        out.print(json);

        out.flush();
        out.close();
    }


    @Override
    public void destroy() {

    }
}
